package creatingPattern.factoryMethod;

/**
 * @Author: Alex Hu
 * Date: 2020/2/22 2:06 下午
 * Content:
 * 工厂方法模式的主要角色如下。
 * 抽象工厂（Abstract Factory）：提供了创建产品的接口，调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
 * 具体工厂（ConcreteFactory）：主要是实现抽象工厂中的抽象方法，完成具体产品的创建。
 * 抽象产品（Product）：定义了产品的规范，描述了产品的主要特性和功能。
 * 具体产品（ConcreteProduct）：实现了抽象产品角色所定义的接口，由具体工厂来创建，它同具体工厂之间一一对应。
 */

import javax.swing.*;
import java.awt.*;

/**
 * 动物接口
 * 设计意图：定义产品的规范，描述产品的主要特性和功能
 * 使用场景：当需要创建一系列相关产品时，抽象产品接口可统一产品行为
 */
interface Animal {
    /**
     * 显示动物
     * 设计意图：定义动物的展示行为
     * 使用场景：当需要展示动物信息时，调用此方法
     */
    void show();
}

/**
 * 动物农场接口
 * 设计意图：定义创建产品的接口，让子类决定实例化哪个类
 * 使用场景：当需要创建一系列相关产品时，抽象工厂可统一产品创建行为
 */
interface AnimalFarm {
    /**
     * 创建动物
     * 设计意图：定义创建动物的抽象方法
     * 使用场景：当需要创建动物时，调用此方法
     * @return 返回创建的动物
     */
    Animal newAnimal();
}

/**
 * 工厂方法模式示例：动物农场
 * 设计意图：定义一个创建对象的接口，让子类决定实例化哪个类
 * 使用场景：当需要创建一系列相关对象，但具体类型在运行时才能确定时使用
 */
public class AnimalFarmTest {
    /**
     * 主方法：演示工厂方法模式
     * 设计意图：通过XML配置动态创建工厂和产品
     * 使用场景：当需要根据配置创建不同产品时，调用此方法
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        try {
            Animal a;
            AnimalFarm af;
            af = (AnimalFarm) ReadXML2.getObject();
            a = af.newAnimal();
            a.show();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

/**
 * 马类
 * 设计意图：实现动物接口，提供具体产品行为
 * 使用场景：当需要创建马对象时使用
 */
class Horse implements Animal {
    /**
     * 滚动面板
     * 设计意图：存储滚动面板对象
     * 使用场景：当需要展示马的信息时，使用此字段
     */
    JScrollPane sp;

    /**
     * 窗口
     * 设计意图：存储窗口对象
     * 使用场景：当需要展示马的信息时，使用此字段
     */
    JFrame jf = new JFrame("工厂方法模式测试");

    /**
     * 构造函数
     * 设计意图：初始化马的信息
     * 使用场景：当需要创建马对象时，调用此构造函数
     */
    public Horse() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物：马"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("src/main/java/creatingPattern/factoryMethod/A_Horse.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        /**用户点击窗口关闭*/
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    /**
     * 显示马
     * 设计意图：实现动物的展示行为
     * 使用场景：当需要展示马的信息时，调用此方法
     */
    public void show() {
        jf.setVisible(true);
    }
}

/**
 * 牛类
 * 设计意图：实现动物接口，提供具体产品行为
 * 使用场景：当需要创建牛对象时使用
 */
class Cattle implements Animal {
    /**
     * 滚动面板
     * 设计意图：存储滚动面板对象
     * 使用场景：当需要展示牛的信息时，使用此字段
     */
    JScrollPane sp;

    /**
     * 窗口
     * 设计意图：存储窗口对象
     * 使用场景：当需要展示牛的信息时，使用此字段
     */
    JFrame jf = new JFrame("工厂方法模式测试");

    /**
     * 构造函数
     * 设计意图：初始化牛的信息
     * 使用场景：当需要创建牛对象时，调用此构造函数
     */
    public Cattle() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物：牛"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("src/main/java/creatingPattern/factoryMethod/A_Cattle.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        /**用户点击窗口关闭*/
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    /**
     * 显示牛
     * 设计意图：实现动物的展示行为
     * 使用场景：当需要展示牛的信息时，调用此方法
     */
    public void show() {
        jf.setVisible(true);
    }
}

/**
 * 养马场类
 * 设计意图：实现动物农场接口，提供具体工厂行为
 * 使用场景：当需要创建马对象时使用
 */
class HorseFarm implements AnimalFarm {
    /**
     * 创建马
     * 设计意图：实现创建动物的抽象方法
     * 使用场景：当需要创建马时，调用此方法
     * @return 返回创建的马
     */
    public Animal newAnimal() {
        System.out.println("新马出生！");
        return new Horse();
    }
}

/**
 * 养牛场类
 * 设计意图：实现动物农场接口，提供具体工厂行为
 * 使用场景：当需要创建牛对象时使用
 */
class CattleFarm implements AnimalFarm {
    /**
     * 创建牛
     * 设计意图：实现创建动物的抽象方法
     * 使用场景：当需要创建牛时，调用此方法
     * @return 返回创建的牛
     */
    public Animal newAnimal() {
        System.out.println("新牛出生！");
        return new Cattle();
    }
}